package com.mhtech.client;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class SchoolClient extends WindowAdapter implements ActionListener {

	private static final String remoteAddress = "120.25.220.177:8080";

	
	private static String schoolMark = "zhongshandaxue";
	private static String localTableName = "paid_local";
	
	private static final String JDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
	private static String localConnectAddress = "jdbc:sqlserver://localhost:";
	
	private static String TAG = "SchoolClient1";

	private static String strSave = "保存";
	private static String strLaunch = "启动";
	private static String strPauseScroll = "暂停/继续滚屏";
	private static String strShutDown = "停止";
	private static String strClean = "清屏";

	private static String strDBName = "dbName";
	private static String strDBPort = "dbPort";
	private static String strDBUser = "dbUser";
	private static String strDBPW = "dbPW";

	private static String dbName = "";
	private static String dbPort = "1433";
	private static String dbUser = "";
	private static String dbPW = "";

	private static JTextArea jta;
	private static boolean scrollFlag = true;

	JTextField jtfDBName;
	JTextField jtfDBPort;
	JTextField jtfDBUser;
	JPasswordField jtfDBPW;

	public SchoolClient() {
		JFrame f = new JFrame("英德中学水电一卡通充值系统--校方客户端");
		f.setSize(450, 500);
		f.setLocation(300, 150);
		f.setLayout(new BorderLayout(5, 5));
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.addWindowListener(this);

		Container c = f.getContentPane();

		JPanel p = new JPanel();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));

		JPanel p1 = new JPanel();
		JLabel lDBName = new JLabel("SQL数据库名:");
		jtfDBName = new JTextField(15);
		JLabel lDBPort = new JLabel("端口:");
		jtfDBPort = new JTextField(5);
		jtfDBPort.setText("1433");
		p1.add(lDBName);
		p1.add(jtfDBName);
		p1.add(lDBPort);
		p1.add(jtfDBPort);
		p.add(p1);

		JPanel p2 = new JPanel();
		JLabel lDBUser = new JLabel("用户名:");
		jtfDBUser = new JTextField(10);
		JLabel lDBPW = new JLabel("密码:");
		jtfDBPW = new JPasswordField(10);
		JButton btnSave = new JButton(strSave);
		btnSave.addActionListener(this);
		p2.add(lDBUser);
		p2.add(jtfDBUser);
		p2.add(lDBPW);
		p2.add(jtfDBPW);
		p2.add(btnSave);
		p.add(p2);

		JPanel p3 = new JPanel();
		JButton btnLaunch = new JButton(strLaunch);
		JButton btnShutDown = new JButton(strShutDown);
		JButton btnPauseScroll = new JButton(strPauseScroll);
		JButton btnClean = new JButton(strClean);
		btnLaunch.addActionListener(this);
		btnShutDown.addActionListener(this);
		btnPauseScroll.addActionListener(this);
		btnClean.addActionListener(this);
		p3.add(btnLaunch);
		p3.add(btnShutDown);
		p3.add(btnPauseScroll);
		p3.add(btnClean);
		p.add(p3);

		jta = new JTextArea();
		jta.setLineWrap(true);
		JScrollPane jsp = new JScrollPane(jta);

		c.add(p, BorderLayout.NORTH);
		c.add(jsp, BorderLayout.CENTER);
		c.add(new JLabel(), BorderLayout.EAST);
		c.add(new JLabel(), BorderLayout.WEST);
		c.add(new JLabel(), BorderLayout.SOUTH);

		f.setVisible(true);

		readProperty();
	}

	public static void main(String[] args) {
		new SchoolClient();
	}

	// ---------------业务处理--开始--------------------------------------------------
	// --定时器--开始
	static Timer timer;
	static TimerTask tt;

	private static void getData() {

		tt = new TimerTask() {

			@Override
			public void run() {
				try {
					SimpleDateFormat sdf = new SimpleDateFormat(
							"yyyy-MM-dd HH:mm:ss");
					insertUpdateText(sdf.format(new Date()) + " \n");

					connect(getDataFromUrl(schoolMark));

				} catch (JSONException e) {
					e.printStackTrace();
					insertUpdateText(e.getMessage() + "\n");
				}
			}
		};

		timer.schedule(tt, 0, 3 * 1000);
	}

	// --------定时器--结束------------------------------------

	// --本地数据库处理--开始
	private static void connect(String values[][]) {
		if (values == null || values.length <= 0) {
			insertUpdateText("没有新充值数据" + "\n");
			return;
		}
		insertUpdateText("获取到数据: " + values.length + "条\n");

		
		// 数据库端口及数据库名(校方本地数据库)
		String connectDB = localConnectAddress + dbPort + ";DatabaseName=" + dbName;

		try {
			// 加载数据库驱动com.microsoft.sqlserver.jdbc.SQLServerDriver
			Class.forName(JDriver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			insertUpdateText("链接数据库失败:" + e.getMessage() + "\n");
		}

		try {
			String user = dbUser;
			String password = dbPW;
			//
			Connection con = DriverManager.getConnection(connectDB, user,
					password);
			Statement stmt = con.createStatement();

			insertUpdateText("正在插入信息..." + "\n");
			CallableStatement proc = con
					.prepareCall("{? = call CheckAndInsert(?)}");
			int count = 0;
			for (int i = 0; i < values.length; i++) {

				proc.setString(2, values[i][1]);
				proc.registerOutParameter(1, java.sql.Types.INTEGER);
				proc.execute();
				if (proc.getInt(1) == 1) {
					String sql = String.format("INSERT INTO " + localTableName
							+ "(time_stamp, out_trade_no,"
							+ "phone_number, name, card_number, rmb, school_mark) "
							+ "VALUES('%s','%s','%s','%s','%s','%s','%s')",
							values[i][0], values[i][1], values[i][2],
							values[i][3], values[i][4], values[i][5],values[i][6]);
					count += stmt.executeUpdate(sql);

				} else {
					insertUpdateText("存在相同的记录！" + "\n");
				}

			}
			insertUpdateText("将要插入: " + count + " 条\n");
			proc.close();

			// -------------如果插入成功应该把信息返回给服务器，
			// 通知服务器修改删除paid_temp相关数据
			// 把已经成功处理的数据项的out_trade_no保存到successValues数组中
			String[] successValues = new String[values.length];
			for (int i = 0; i < values.length; i++) {
				successValues[i] = values[i][1];
			}
			insertUpdateText("正在通知服务器删除数据!" + "\n");
			deleteSuccessValues(successValues);

			insertUpdateText("插入信息成功!" + "\n");

			stmt.close();
			con.close();
		} catch (SQLException e) {
			insertUpdateText(e.getMessage() + "\n");
			e.printStackTrace();
		}
	}

	private static String[][] getDataFromUrl(String schoolMark)
			throws JSONException {

		String url = "http://" + remoteAddress + 
				"/MyWebAppPay/GetDataServlet?school_mark=" + schoolMark;
		byte[] buf = Util.httpGet(url);

		if (buf == null || buf.length == 0) {
			insertUpdateText("网络异常,请检查网络是否连通" + "\n");
			return null;
		}
		String content = new String(buf);
		String[][] values;

		String time_stamp;
		String out_trade_no;
		String phone_number;
		String name;
		String card_number;
		String rmb;
		String school_mark;

		JSONArray jsonArray = new JSONArray(content);
//		insertUpdateText(jsonArray.toString() + "\n");
		values = new String[jsonArray.length()][7];
		for (int i = 0; i < jsonArray.length(); i++) {
			JSONObject jsonObject = jsonArray.getJSONObject(i);

			time_stamp = jsonObject.getString("time_stamp");
			out_trade_no = jsonObject.getString("out_trade_no");
			phone_number = jsonObject.getString("phone_number");
			name = jsonObject.getString("name");
			card_number = jsonObject.getString("card_number");
			rmb = jsonObject.getString("rmb");
			school_mark = jsonObject.getString("school_mark");
			values[i][0] = time_stamp;
			values[i][1] = out_trade_no;
			values[i][2] = phone_number;
			values[i][3] = name;
			values[i][4] = card_number;
			values[i][5] = rmb;
			values[i][6] = school_mark;

		}
		return values;

	}

	private static void deleteSuccessValues(String[] successValues) {

		if (successValues == null || successValues.length <= 0) {
			return;
		}
		StringBuilder stringBuilder = new StringBuilder();
		String value = "";
		for (int i = 0; i < successValues.length; i++) {
			try {
				value = URLEncoder.encode(successValues[i], "utf-8");
				stringBuilder.append(value).append(",");
			} catch (UnsupportedEncodingException e) {
				insertUpdateText(e.getMessage() + "\n");
				e.printStackTrace();
			}

		}
		stringBuilder.deleteCharAt(stringBuilder.length() - 1);// 删除末尾的","

		String url = "http://" + remoteAddress
				+ "/MyWebAppPay/GetInfoFromSchoolClient?successValues="
				+ stringBuilder.toString();

		byte[] buf = Util.httpGet(url);

		if (buf == null || buf.length == 0) {
			insertUpdateText("通知服务器删除数据时,网络异常" + "\n");
			return;
		}
		String content = new String(buf);
		insertUpdateText(TAG + "删除成功,共删除 : " + content + " 条\n");
	}

	// --本地数据库处理--结束-----------------------------------------------
	// ---------------业务处理--结束-------------------------------------------------

	private void readProperty() {

		try {
			Properties prop = new Properties();
			// 读取属性文件school_client_property.ini
			InputStream in = new BufferedInputStream(new FileInputStream(
					"school_client_property.ini"));
			// /加载属性列表
			prop.load(in);
			dbName = prop.getProperty(strDBName);
			dbUser = prop.getProperty(strDBUser);
			dbPW = prop.getProperty(strDBPW);
			dbPort = prop.getProperty(strDBPort);
			// 密码要解密
			dbPW = DeEncode.decode(dbPW);

			jtfDBName.setText(dbName);
			jtfDBUser.setText(dbUser);
			jtfDBPW.setText(dbPW);
			jtfDBPort.setText(dbPort);

			in.close();
			if (dbName.equals("") || dbUser.equals("") || dbPW.equals("")) {
				return;
			}
			if (timer != null) {
				timer.cancel();
			}
			timer = null;
			timer = new Timer();
			if(checkDBUserData() != 1){
				insertUpdateText("登陆本地数据库失败,请确认数据库名、用户名、密码、端口号及" +
						"用户名的身份验证方式是否正确。更详细的说明请参考使用说明。\n");
				return;
			}
			getData();
		} catch (FileNotFoundException e) {
			insertUpdateText(e.getMessage() + "\n");
			e.printStackTrace();
		} catch (IOException e) {
			insertUpdateText(e.getMessage() + "\n");
			e.printStackTrace();
		}
	}

	public void saveProperty(String dbName, String dbUser, String dbPW, String dbPort) {
		try {
			if(checkDBUserData() != 1){
				insertUpdateText("登陆本地数据库失败,请确认数据库名、用户名、密码、端口号及" +
						"用户名的身份验证方式是否正确。更详细的说明请参考使用说明。\n");
				return;
			}
			Properties prop = new Properties();
			// 保存属性到school_client_property.ini文件
			FileOutputStream oFile = new FileOutputStream(
					"school_client_property.ini", false);
			prop.setProperty(strDBName, dbName);
			prop.setProperty(strDBUser, dbUser);
			// 密码要加密
			prop.setProperty(strDBPW, DeEncode.encode(dbPW));
			prop.setProperty(strDBPort, dbPort);
			
			prop.store(oFile, "The New properties file");

			oFile.close();
			insertUpdateText("保存用户信息成功!\n");
		} catch (IOException e) {
			insertUpdateText(e.getMessage() + "\n");
			e.printStackTrace();
		}
	}

	public static void insertUpdateText(String text) {
		jta.append(text);
		if (scrollFlag) {
			jta.setCaretPosition(jta.getText().length());
		}
	}

	private static int checkDBUserData() {
		
		// 数据库端口及数据库名(校方本地数据库)
		String connectDB = localConnectAddress + dbPort + ";DatabaseName=" + dbName;
		
		try {
			// 加载数据库驱动com.microsoft.sqlserver.jdbc.SQLServerDriver
			Class.forName(JDriver);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			insertUpdateText("链接数据库失败:" + e.getMessage() + "\n");
		}

		try {
			String user = dbUser;
			String password = dbPW;
			//
			Connection con = DriverManager.getConnection(connectDB, user, password);
			con.close();
			return 1;
		} catch (SQLException e) {
			insertUpdateText(e.getMessage()+"\n");
			return -1;
		}
	}
//-------------监听重载------------------------------------------------------------
	@SuppressWarnings("deprecation")
	@Override
	public void actionPerformed(ActionEvent e) {

		if (e.getActionCommand().equals(strSave)) {
			String dbName_temp = jtfDBName.getText();
			String dbUser_temp = jtfDBUser.getText();
			String dbPW_temp = jtfDBPW.getText();
			String dbPort_temp = jtfDBPort.getText();
			System.out.println(dbPort_temp);
			if (dbName_temp.equals("") || dbUser_temp.equals("")
					|| dbPW_temp.equals("") || dbPort_temp.equals("")) {
				insertUpdateText("数据库名 或者 用户名 或者 密码 或者 端口为空!\n");
				return;
			}
			dbName = dbName_temp;
			dbUser = dbUser_temp;
			dbPW = dbPW_temp;
			dbPort = dbPort_temp;

			saveProperty(dbName, dbUser, dbPW, dbPort);

		} else if (e.getActionCommand().equals(strLaunch)) {
			if (dbName.equals("") || dbUser.equals("") || dbPW.equals("") || dbPort.equals("")) {
				insertUpdateText("数据库名 或者 用户名 或者 密码 或者 端口  为空!\n");
				return;
			}
			if (timer != null) {
				timer.cancel();
			}
			timer = null;
			timer = new Timer();
			if(checkDBUserData() != 1){
				insertUpdateText("登陆本地数据库失败,请确认数据库名、用户名、密码、端口号及" +
						"用户名的身份验证方式是否正确。更详细的说明请参考使用说明。\n");
				return;
			}
			getData();
		} else if (e.getActionCommand().equals(strPauseScroll)) {
			scrollFlag = !scrollFlag;
		} else if (e.getActionCommand().equals(strShutDown)) {
			if(timer != null){
				timer.cancel();
			}
			insertUpdateText("\n 已停止联网获取数据. \n");
		} else if (e.getActionCommand().equals(strClean)) {
			jta.setText("");
		}
	}

	@Override
	public void windowClosing(WindowEvent e) {

		super.windowClosing(e);
	}

}
